package gew.data;

import gew.system.Labels;
import gew.utils.SqlUtils;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Locale;

public class TradeSummaryItem {

    private final static int GROUP_PARTNER = 4;
    private final static int GROUP_COMMODITY = 8;
    private final static int TOP_LIMIT = 10;
    private final static int SHARE_TOTAL = 10000;
    private final static String OTHERS_COLOR = "#ddd";
    private final static String USD = "$ ";

    private final static int FIELD_INDEX_ID = 1;
    private final static int FIELD_INDEX_PARENT_ID = 2;
    private final static int FIELD_INDEX_REPORTER_NAME = 3;
    private final static int FIELD_INDEX_EXP_GROUP_NAME = 4;
    private final static int FIELD_INDEX_IMP_GROUP_NAME = 5;
    private final static int FIELD_INDEX_KIDS = 6;
    private final static int FIELD_INDEX_LVL = 7;
    private final static int FIELD_INDEX_OPEN = 8;
    private final static int FIELD_INDEX_HAS_CHILD = 9;
    private final static int FIELD_INDEX_LAST_PERIOD_ID = 10;
    private final static int FIELD_INDEX_EXP_TRADE_VALUE = 11;
    private final static int FIELD_INDEX_IMP_TRADE_VALUE = 12;
    private final static int FIELD_INDEX_EXP_URL = 13;
    private final static int FIELD_INDEX_IMP_URL = 14;
    private final static int FIELD_INDEX_EXP_IMP_URL = 15;

    private final static int FIELD_INDEX_EXP_SHARES = 16;
    private final static int FIELD_INDEX_IMP_SHARES = 17;
    private final static int FIELD_INDEX_EXP_COLORS = 18;
    private final static int FIELD_INDEX_IMP_COLORS = 19;

    private final static int FIELD_INDEX_EXP_URL_CODES = 20;
    private final static int FIELD_INDEX_IMP_URL_CODES = 21;
    private final static int FIELD_INDEX_EXP_NAMES = 22;
    private final static int FIELD_INDEX_IMP_NAMES = 23;
    private final static int FIELD_INDEX_EXP_VALUES = 24;
    private final static int FIELD_INDEX_IMP_VALUES = 25;

    private final static int FIELD_INDEX_GROUP_ID = 26;
    private final static int FIELD_INDEX_REPORTER_COLOR = 27;
    private final static int FIELD_INDEX_REPORTER_URL_CODE = 28;
    private final static int FIELD_INDEX_EXP_CODES = 29;
    private final static int FIELD_INDEX_IMP_CODES = 30;
    private final static int FIELD_INDEX_EXP_TRADE_VALUE_STR = 31;
    private final static int FIELD_INDEX_IMP_TRADE_VALUE_STR = 32;

    private final int id;
    private final int parentId;
    private final String reporterName;
    private final String expGroupName;
    private final String impGroupName;
    private final byte kids;
    private final int lvl;
    private final byte open;
    private final byte hasChild;
    private final Integer lastPeriodId;
    private final Long expTradeValue;
    private final Long impTradeValue;
    private final String expUrl;
    private final String impUrl;
    private final String expImpUrl;
    private final String expShares;
    private final String impShares;
    private final String expColors;
    private final String impColors;
    private final String expUrlCodes;
    private final String impUrlCodes;
    private final String expNames;
    private final String impNames;
    private final String expValues;
    private final String impValues;
    private final int groupId;
    private final String reporterColor;
    private final String reporterUrlCode;
    private final String expCodes;
    private final String impCodes;
    private ArrayList<TradeSummaryItemDetail> detailsExport;
    private ArrayList<TradeSummaryItemDetail> detailsImport;
    private Locale locale;
    private NumberFormat numberFormat;
    private NumberFormat percentFormat;
    private final String expTradeValueStr;
    private final String impTradeValueStr;

    public TradeSummaryItem(ResultSet rs) throws SQLException {
        id = rs.getInt(FIELD_INDEX_ID);
        parentId = rs.getInt(FIELD_INDEX_PARENT_ID);
        reporterName = rs.getString(FIELD_INDEX_REPORTER_NAME);
        expGroupName = rs.getString(FIELD_INDEX_EXP_GROUP_NAME);
        impGroupName = rs.getString(FIELD_INDEX_IMP_GROUP_NAME);
        kids = rs.getByte(FIELD_INDEX_KIDS);
        lvl = rs.getInt(FIELD_INDEX_LVL);
        open = rs.getByte(FIELD_INDEX_OPEN);
        hasChild = rs.getByte(FIELD_INDEX_HAS_CHILD);
        if (rs.getObject(FIELD_INDEX_LAST_PERIOD_ID) != null) {
            lastPeriodId = rs.getInt(FIELD_INDEX_LAST_PERIOD_ID);
        } else {
            lastPeriodId = null;
        }
        if (rs.getObject(FIELD_INDEX_EXP_TRADE_VALUE) != null) {
            expTradeValue = rs.getLong(FIELD_INDEX_EXP_TRADE_VALUE);
        } else {
            expTradeValue = null;
        }
        if (rs.getObject(FIELD_INDEX_IMP_TRADE_VALUE) != null) {
            impTradeValue = rs.getLong(FIELD_INDEX_IMP_TRADE_VALUE);
        } else {
            impTradeValue = null;
        }
        expUrl = rs.getString(FIELD_INDEX_EXP_URL);
        impUrl = rs.getString(FIELD_INDEX_IMP_URL);
        expImpUrl = rs.getString(FIELD_INDEX_EXP_IMP_URL);
        expShares = rs.getString(FIELD_INDEX_EXP_SHARES);
        impShares = rs.getString(FIELD_INDEX_IMP_SHARES);
        expColors = rs.getString(FIELD_INDEX_EXP_COLORS);
        impColors = rs.getString(FIELD_INDEX_IMP_COLORS);
        expUrlCodes = rs.getString(FIELD_INDEX_EXP_URL_CODES);
        impUrlCodes = rs.getString(FIELD_INDEX_IMP_URL_CODES);
        expNames = rs.getString(FIELD_INDEX_EXP_NAMES);
        impNames = rs.getString(FIELD_INDEX_IMP_NAMES);
        expValues = rs.getString(FIELD_INDEX_EXP_VALUES);
        impValues = rs.getString(FIELD_INDEX_IMP_VALUES);
        groupId = rs.getInt(FIELD_INDEX_GROUP_ID);
        reporterColor = rs.getString(FIELD_INDEX_REPORTER_COLOR);
        reporterUrlCode = rs.getString(FIELD_INDEX_REPORTER_URL_CODE);
        expCodes = rs.getString(FIELD_INDEX_EXP_CODES);
        impCodes = rs.getString(FIELD_INDEX_IMP_CODES);
        expTradeValueStr = USD.concat(rs.getString(FIELD_INDEX_EXP_TRADE_VALUE_STR));
        impTradeValueStr = USD.concat(rs.getString(FIELD_INDEX_IMP_TRADE_VALUE_STR));
    }

    public int getId() {
        return id;
    }

    public int getParentId() {
        return parentId;
    }

    public byte getKids() {
        return kids;
    }

    public int getLvl() {
        return lvl;
    }

    public byte getOpen() {
        return open;
    }

    public byte getHasChild() {
        return hasChild;
    }

    public Integer getLastPeriodId() {
        return lastPeriodId;
    }

    public Long getExpTradeValue() {
        return expTradeValue;
    }

    public Long getImpTradeValue() {
        return impTradeValue;
    }

    public String getExpUrl() {
        return expUrl;
    }

    public String getImpUrl() {
        return impUrl;
    }

    public String getExpImpUrl() {
        return expImpUrl;
    }

    public Boolean hasLink() {
        return !(expImpUrl == null || expImpUrl.isEmpty());
    }

    public String getExpShares() {
        return expShares;
    }

    public String getImpShares() {
        return impShares;
    }

    public String getExpColors() {
        return expColors;
    }

    public String getImpColors() {
        return impColors;
    }

    public String getExpUrlCodes() {
        return expUrlCodes;
    }

    public String getImpUrlCodes() {
        return impUrlCodes;
    }

    public String getExpNames() {
        return expNames;
    }

    public String getImpNames() {
        return impNames;
    }

    public String getExpValues() {
        return expValues;
    }

    public String getImpValues() {
        return impValues;
    }

    public String getReporterName() {
        return reporterName;
    }

    public String getExpGroupName() {
        return expGroupName;
    }

    public String getImpGroupName() {
        return impGroupName;
    }

    public int getGroupId() {
        return groupId;
    }

    public String getReporterColor() {
        return reporterColor;
    }

    public String getReporterUrlCode() {
        return reporterUrlCode;
    }

    public String getExpCodes() {
        return expCodes;
    }

    public String getImpCodes() {
        return impCodes;
    }

    public boolean isGroupPartner() {
        return this.groupId == GROUP_PARTNER;
    }

    public void setLocale(Locale locale) {
        this.locale = locale;
    }

    public void setNumberFormat(NumberFormat numberFormat) {
        this.numberFormat = numberFormat;
    }

    public void setPercentFormat(NumberFormat percentFormat) {
        this.percentFormat = percentFormat;
    }

    public Collection<TradeSummaryItemDetail> getDetailsExport() {
        if (detailsExport == null) {
            detailsExport = getDetails(
                    this.expUrlCodes.split(SqlUtils.SPACE),
                    this.expShares.split(SqlUtils.SPACE),
                    this.expNames.split(SqlUtils.HYPHEN.concat(SqlUtils.HYPHEN)),
                    this.expValues.split(SqlUtils.SPACE),
                    this.expColors.split(SqlUtils.SPACE),
                    this.expCodes.split(SqlUtils.SPACE),
                    isGroupPartner() ? Labels.get_UI_TITLE_MORE_PARTNERS(locale) : Labels.get_UI_TITLE_MORE_COMMODITIES(locale),
                    numberFormat, percentFormat);
        }
        return detailsExport;
    }

    public Collection<TradeSummaryItemDetail> getDetailsImport() {
        if (detailsImport == null) {
            detailsImport = getDetails(
                    this.impUrlCodes.split(SqlUtils.SPACE),
                    this.impShares.split(SqlUtils.SPACE),
                    this.impNames.split(SqlUtils.HYPHEN.concat(SqlUtils.HYPHEN)),
                    this.impValues.split(SqlUtils.SPACE),
                    this.impColors.split(SqlUtils.SPACE),
                    this.impCodes.split(SqlUtils.SPACE),
                    isGroupPartner() ? Labels.get_UI_TITLE_MORE_PARTNERS(locale) : Labels.get_UI_TITLE_MORE_COMMODITIES(locale),
                    numberFormat, percentFormat);
        }
        return detailsImport;
    }

    private static ArrayList<TradeSummaryItemDetail> getDetails(
            String[] urls, String[] shares,
            String[] names, String[] values,
            String[] colors, String[] codes,
            String othersName, NumberFormat numberFormat, NumberFormat percentFormat) {
        ArrayList<TradeSummaryItemDetail> details = new ArrayList<>();
        if (values.length == 1 && values[0].isEmpty())
            return details;
        int count = Math.min(Math.min(
                Math.min(urls.length, shares.length),
                Math.min(names.length, values.length)),
                Math.min(colors.length, codes.length));
        Integer topShare = 0;
        Long topValue = (long) 0;
        for (int i = 0; i < Math.min(TOP_LIMIT, count); i++) {
            details.add(new TradeSummaryItemDetail(
                    urls[i], shares[i], names[i], values[i], colors[i], codes[i], numberFormat, percentFormat
            ));
            topShare += Integer.parseInt(shares[i]);
            topValue += Long.parseLong(values[i]);
        }
        if (TOP_LIMIT < count) {
            int othersCount = Math.min(TOP_LIMIT, count);
            String[] otherUrls = Arrays.copyOfRange(urls, 0, othersCount);
            Arrays.sort(otherUrls);
            TradeSummaryItemDetail othersItem = new TradeSummaryItemDetail(
                    String.join(SqlUtils.HYPHEN, otherUrls),
                    (SHARE_TOTAL - topShare),
                    othersName,
                    (long) (SHARE_TOTAL * topValue / topShare),
                    OTHERS_COLOR, SqlUtils.EMPTY, true, numberFormat, percentFormat
            );
            details.add(othersItem);
        }
        return details;
    }

    public String getExpTradeValueStr() {
        return expTradeValueStr;
    }

    public String getImpTradeValueStr() {
        return impTradeValueStr;
    }

}
